<?php

    /**
     * Http
     *
     * @package      Core
     * @subpackage   Controller_Response
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    class Core_Controller_Response_Http extends Core_Controller_Response_Abstract
    {

	////////////////////////////////////////////////////////////////////////////
	//                                Variables                               //
	////////////////////////////////////////////////////////////////////////////

        /**
         * The Dwoo data set
         *
         * @var Dwoo_Data
         */
        public $data = null;

        /**
        * The Dwoo template
        *
        * @var Dwoo_Template_File
        */
        protected $_tpl = null;

        /**
        * The response type
        *
        * @var string
        */
        protected $_type = 'http';

        /**
         * The charset of the document
         *
         * @var string
         */
        protected $_charset;

        /**
         * Singleton instance
         *
         * Marked only as protected to allow extension of the class.
         * To extend, simply override {@link getInstance()}.
         *
         * @var Core_Controller_Response_Http
         */
        protected static $_instance = null;

	////////////////////////////////////////////////////////////////////////////
	//                            Getters / Setters                           //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Sets the template to use
         *
         * @param       string      $value : the selector of the template
		 * @throws		Core_Exception
		 * @throws		Core_ArgumentException
		 * @throws		Core_ArgumentNullException
         * @return      Core_Controller_Response_Http
         */
        public function setTemplate($value)
        {
            if ($value === null) {
				throw new Core_ArgumentNullException('value is a null reference');
			}

            if (strlen(trim($value)) == 0) {
				throw new Core_ArgumentException('value is a zero-length string');
			}

            // set the module's & file's name
            if (preg_match("/^(([a-zA-Z0-9_\.]+)~)([a-zA-Z0-9_\.]+)$/", $value, $m)) {
                if ($m[1] != '' && $m[2] != '') {
                    $module = ucfirst(strtolower($m[2]));
                } else {
                    $module = Core_Context::get();
                }

                $filename = $m[3];
            } else {
                $module = '';
                $filename = $value;
            }

            $end = 'frontend';

            if (($this->_registry['end'] == 'admin')) {
                $end = 'backend';
            } elseif (($this->_registry['end'] == 'cron')) {
                $end = 'cron';
            }

            $paths = array(Core_IO_Path::combine(
                                PROJECT_WWW_PATH,
                                'skin',
                                $end,
                                ((empty($module)) ? '' : 'modules'),
                                ucfirst(strtolower($module)),
                                'templates',
                                $filename
                            ),
                            Core_IO_Path::combine(
                                SERUM_WWW_PATH,
                                'skin',
                                $end,
                                ((empty($module)) ? '' : 'modules'),
                                ucfirst(strtolower($module)),
                                'templates',
                                $filename
                            ));

            $path = null;
            foreach ($paths as $currentPath) {
	            if (Core_IO_File::exists($currentPath)) {
	                $path = $currentPath;
	                break;
	            }
            }
            
            if ($path == null) {
                throw new Core_Exception('Unable to load template '. $value);
            }

            $this->_tpl = new Dwoo_Template_File($path);

            return $this;
        }

	////////////////////////////////////////////////////////////////////////////
	//                             Static Methods                             //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Singleton instance
         * Returns the current instance (used to access the response from the template)
         *
         * @return      Core_Controller_Response_Http|null
         */
        public static function getInstance()
        {
            return self::$_instance;
        }

	////////////////////////////////////////////////////////////////////////////
	//                                 Methods                                //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Constructor
         *
         * Sets the charset, the language and the template engine
         */
        public function __construct()
        {
            parent::__construct();

            self::$_instance = $this;
            $this->data      = new Dwoo_Data();
            $this->_charset  = $this->_registry['config']->view->encoding;
        }

        /**
         * Outputs the HTML content
         *
         * @throws      Core_Exception
         * @return      boolean     true if the generated content is ok
         */
        public final function output()
        {
            $this->_httpHeadersSent = false;
            $this->_httpHeaders['Content-Type'] = 'text/html;charset='. $this->_charset;

            Core_Storage_Cookie::getInstance()->getMatchingCookies();

            if (!($this->_tpl instanceof Dwoo_Template_File)) {
                throw new Core_Exception('Fatal error: template isn\'t an instance of Dwoo_Template_File');
            }

            if ($this->_registry['end'] == 'admin') {
                $this->data->assign('SKIN_SERUM',   $this->_registry['config']->urlengine->basePath . 'serum/skin/backend/');
                $this->data->assign('SKIN_PROJECT', $this->_registry['config']->urlengine->basePath . 'project/skin/backend/');
                $this->data->assign('TEMP',         $this->_registry['config']->urlengine->basePath . 'project/temp/');

                /*
                 * Serum.min.js
                 */
                $dirRoot         = Core_IO_Path::combine('skin', 'backend', 'js', 'Serum');
                $moduleDir       = Core_IO_Path::combine('skin', 'backend', 'modules');
                $projectDirRoot  = Core_IO_Path::combine(PROJECT_WWW_PATH, $dirRoot);

                $directories     = array(
                                         Core_IO_Path::combine(SERUM_WWW_PATH, $dirRoot),
                                         Core_IO_Path::combine(SERUM_WWW_PATH, $moduleDir),
                                         $projectDirRoot,
                                         Core_IO_Path::combine(PROJECT_WWW_PATH, $moduleDir)
                                     );

                if (!Core_IO_Directory::exists($projectDirRoot)) {
                    Core_IO_Directory::createDirectory($projectDirRoot);
                }

                $compressedFile     = Core_IO_Path::combine(PROJECT_TEMP_PATH, 'Serum.min.js');
                $content            = '';

                foreach ($directories as $currentDir) {
                    if (Core_IO_Directory::exists($currentDir)) {
                        foreach (Core_IO_Directory::getFiles($currentDir, true, true, array('.js', '.js.php')) as $jsFile) {
                            $content .= Core_IO_File::readAll($jsFile) . "\n";
                        }
                    }
                }

                Core_IO_File::writeAll($compressedFile, $content);

            } else {
                $this->data->assign('SKIN_SERUM',   $this->_registry['config']->urlengine->basePath . 'serum/skin/frontend/');
                $this->data->assign('SKIN_PROJECT', $this->_registry['config']->urlengine->basePath . 'project/skin/frontend/');
            }

            $this->data->assign('METER',        Core_Meter::getInstance()->getFirebugText());
            $this->data->assign('DOMAIN',      'http://'. $_SERVER['HTTP_HOST']);
            $this->data->assign('BASEURL',      $this->_registry['config']->urlengine->basePath);

            $dwoo = new Dwoo(Core_IO_Path::combine(PROJECT_TEMP_TEMPLATES, 'compiled'), Core_IO_Path::combine(PROJECT_TEMP_TEMPLATES, 'cache'));
            $dwoo->output($this->_tpl, $this->data);

            return true;
        }

        /**
         * Outputs the errors
         *
         * @return      void
         */
        public final function outputErrors()
        {
            if (!$this->_httpHeadersSent) {
                header("HTTP/1.0 500 Internal Server Error");
                header('Content-Type: text/html; charset='. $this->_charset);

                $this->_httpHeadersSent = true;
            }

            if ($this->hasErrors()) {
                $errors = $this->_coordinator->getErrorMessages();

                foreach ($errors as $e) {
                   echo '<p style="margin: 0px;"><strong>['. $e[0] .' '. $e[1] .']</strong> <span style="color: #FF0000">'. htmlspecialchars($e[2], ENT_NOQUOTES, $this->_charset) ."</span> \t". $e[3] ." \t". $e[4] ."</p>\n";
                }
            } else {
                echo '<p style="color: #FF0000">Unknow Error</p>';
            }
        }
    }
